GLvoid RotateToFace(VECTOR Object, VECTOR LookAt);

GLvoid SetGLLighting()         // Loop through and reset all the lights
{
        light[0].LightNumber = 0;
        light[0].Reset();
        light[0].UpdatePosition(0,
                                Height(g_HeightMap, (xzoffset) / scaleValue,
                                 (xzoffset) /scaleValue)*(scaler)
                                + yoffset,
                                0);
        light[0].Positional = FALSE; //TRUE;
        light[0].Ambient[0] = 0.9;
        light[0].Ambient[1] = 0.9;
        light[0].Ambient[2] = 0.9;
        light[0].Update();
        glEnable(GL_LIGHTING);
}

GLvoid SetGLCamera()          // Loop through and reset all the cameras
{
        if (otherviewactive == FALSE) {
           camera[0].Reset();
           camera[0].UpdatePosition(10.3, 17.5, 24.5);
           camera[0].UpdateOrientation(0.37, -0.185, -0.053, 1.107);
        }
        else {
           camera[0].Reset();
           camera[0].UpdatePosition(0.0, 35.0, 0.0);
           camera[0].UpdateOrientation(-0.707, 0.0, 0.0, -0.707);
        }

}

GLvoid SetGLProperties()
{
    glCullFace(GL_BACK);
    glClearColor(0.15f, 0.15f, 0.15f, 0.0f);
    glClearDepth(1.0);
    glDepthFunc(GL_LESS);
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);
    glEnable(GL_NORMALIZE);
    glEnable(GL_CULL_FACE);
}

GLvoid SetFog()
{
        GetWindowRect(GetDesktopWindow(), &desktop_window);

	glFogCoordfEXT	= (PFNGLFOGCOORDFEXTPROC) wglGetProcAddress("glFogCoordfEXT");
	if(!glFogCoordfEXT)
	{
		MessageBox(g_window->hWnd, "Your current setup does not support volumetric fog", "Error", MB_OK);
		PostQuitMessage(0);
	}
	float fogColor[4] = {0.5f, 0.5f, 0.5f, 1.0f};

	glEnable(GL_FOG);	      			// Turn on fog
	glFogi(GL_FOG_MODE, GL_LINEAR);			// Set the fog mode to LINEAR (Important)
	glFogfv(GL_FOG_COLOR, fogColor);		// Give OpenGL our fog color
	glFogf(GL_FOG_START, fogstart);			// Set the start position for the depth at 0
	glFogf(GL_FOG_END, fogend);			// Set the end position for the detph at 50
	glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
}

GLvoid SetGLProjection(GLsizei Width, GLsizei Height)
{
    if (Height==0)
        Height=1;
    glViewport(0, 0, Width, Height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0,(GLfloat)Width/(GLfloat)Height,0.5,200.0);
}

GLvoid SetGLView(GLsizei Width, GLsizei Height)
{
	SetGLProjection(Width, Height);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

GLvoid SetGLMaterial()
{
    GLfloat mat_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat mat_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat mat_specular[] = { 0.9, 0.9, 0.9, 1.0 };
    GLfloat mat_emission[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat mat_shininess[] = { 80.0 };

    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
    glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
}

GLvoid SetGLTexture()            // This function will be rewritten later
{
    sprintf(texture[grass_tex].TexName, "%s", "Textures/grass.tga");
    texture[grass_tex].LoadTGA();
    sprintf(texture[font_tex].TexName, "%s", "Textures/font.tga");
    texture[font_tex].LoadTGA();
    sprintf(texture[wormhole_tex].TexName, "%s", "Textures/wormhole.tga");
    texture[wormhole_tex].LoadTGA();
    sprintf(texture[pandora_tex].TexName, "%s", "Textures/pandora.tga");
    texture[pandora_tex].LoadTGA();
    sprintf(texture[life_tex].TexName, "%s", "Textures/life.tga");
    texture[life_tex].LoadTGA();
    sprintf(texture[apple_tex].TexName, "%s", "Textures/apple.tga");
    texture[apple_tex].LoadTGA();
    sprintf(texture[water_tex].TexName, "%s", "Textures/water.tga");
    texture[water_tex].LoadTGA();
    sprintf(texture[otherview_tex].TexName, "%s", "Textures/otherview.tga");
    texture[otherview_tex].LoadTGA();
    sprintf(texture[glowworm_tex].TexName, "%s", "Textures/glowworm.tga");
    texture[glowworm_tex].LoadTGA();
    sprintf(texture[cross_tex].TexName, "%s", "Textures/cross.tga");
    texture[cross_tex].LoadTGA();
}

GLvoid SetWorm()
{
VECTOR wormsegment;
int wormsegmentno;

    /* Starting at the tail, position the inital placement of each
       worm segment location */
    for (wormsegmentno = 0;
         wormsegmentno < numwormsegments;
         wormsegmentno ++) {
       wormsegment.x = light[0].Position.x - wormdirection.x*(0.1*wormsegmentno);
       wormsegment.z = light[0].Position.z - wormdirection.z*(0.1*wormsegmentno);
       wormsegment.y = Height(g_HeightMap, (wormsegment.x+xzoffset) / scaleValue,
                                          (wormsegment.z+xzoffset) /scaleValue)*(scaler)
                       + yoffset;

       worm.push_back(wormsegment);
    }
}

GLvoid ResetWorm()
{
 begin = worm.begin();
 end = worm.end();
 worm.erase(begin, end);
 numwormsegments=initnumwormsegments;
 wormdirection.Set(wormspeed*1, wormspeed*0, wormspeed*0);
 wormangle.Set(0, pi/4, 0);
 SetGLLighting();
 SetWorm();
}

GLvoid ResetApple()
{
float x;
float y;
float z;
BOOLEAN foundsafeplace = FALSE;

   while (foundsafeplace == FALSE) {
      x = random (20) - 10;
      z = random (20) - 10;
      y = Height(g_HeightMap, (x+xzoffset) / scaleValue,
                              (z+xzoffset) /scaleValue)*(scaler)
             + yoffset;
      apple.Set(x, y, z);

      if ((CheckForCollisionWithWorm(apple, FALSE) == FALSE) &&
          (CheckForCollisionWithTrees(apple) == FALSE))
         foundsafeplace = TRUE;
   }
}

GLvoid ResetWormHole()
{
float x;
float z;
float y;

   for (int loop = 0 ; loop < 2; loop ++){
      x = random (20) - 10;
      z = random (20) - 10;
      y = Height(g_HeightMap, (x+xzoffset) / scaleValue,
                              (z+xzoffset) /scaleValue)*(scaler) + yoffset + 0.2;
      hole[loop].Set(x, y, z);
   }
}

GLvoid ResetTrees()
{
float x;
float y;
float z;

   for (int loop = 0 ; loop < numtrees; loop ++){
     x = random (20) - 10;
     z = random (20) - 10;
     y = Height(g_HeightMap, (x+xzoffset) / scaleValue,
                             (z+xzoffset) /scaleValue)*(scaler)
         + yoffset;
     tree[loop].Set(x, y, z);
   }
}

GLvoid ResetPandora()
{
float x = random (20) - 10;
float z = random (20) - 10;
float y = Height(g_HeightMap, (x+xzoffset) / scaleValue,
                              (z+xzoffset) /scaleValue)*(scaler)
          + yoffset;
   pandora.Set(x, y, z);
}

GLvoid OpenPandora()
{
float x = random (80);

    x = x / 10;
    switch ((int)x) {
      case 1:
         if (waterlevel < maxwaterlevel+1.0)
           waterlevel+=1.0;
         else
           waterlevel=maxwaterlevel;
           PlaySound("Sounds/Thunder.wav", NULL, SND_ASYNC);
        break;
      case 2:
         if (wormspeed < (2 * initialwormspeed)) {
           wormspeed += 1.0;
           PlaySound("Sounds/Fast.wav", NULL, SND_ASYNC);
           break;
         }
      case 3:
         phaseinsegments+=15;
         PlaySound("Sounds/Grow.wav", NULL, SND_ASYNC);
        break;
      case 4:
         if (wormspeed > (initialwormspeed + 1.0)) {
           wormspeed -= 1.0;
           PlaySound("Sounds/Slow.wav", NULL, SND_ASYNC);
           break;
         }
      case 5:
         if (numwormsegments > (initnumwormsegments + 15)) {
           phaseinsegments-=15;
           PlaySound("Sounds/Shrink.wav", NULL, SND_ASYNC);
           return;
         }
      case 6:
         lives++;
           PlaySound("Sounds/Life.wav", NULL, SND_ASYNC);
        break;
      case 7:
         views++;
           PlaySound("Sounds/Otherview.wav", NULL, SND_ASYNC); // Views sound
        break;
      default:
         if (waterlevel < maxwaterlevel+1.0)
           waterlevel+=1.0;
         else
           waterlevel=maxwaterlevel;
           PlaySound("Sounds/Thunder.wav", NULL, SND_ASYNC);
        break;
    }
}

GLvoid TeleportWorm(int hereorthere)
{
   int there;
      there = (hereorthere == 1) ? 0 : 1;
      light[0].Position.x = hole[there].x;
      light[0].Position.y = hole[there].y,
      light[0].Position.z = hole[there].z;
      light[0].Apply();
}

GLvoid DrawLightSphere()
{
    GLfloat mat_ambient[] = { 1.0, 0.2, 0.1, 1.0 };
    GLfloat mat_diffuse[] = { 1.0, 0.2, 0.1, 1.0 };
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
    glDisable(GL_TEXTURE_2D);
    glPushMatrix();
    glTranslatef(light[0].Position.x, light[0].Position.y, light[0].Position.z);
    GLUquadricObj * sphere = gluNewQuadric();
    gluQuadricOrientation(sphere, GLU_OUTSIDE);
    gluSphere(sphere,wormradius,20,20);
    glPopMatrix();
    glEnable(GL_TEXTURE_2D);
}

GLvoid DrawApple()
{
    int x;

    GLfloat mat_ambient[] = { 1.0, 1.0, 1.0, 0.0 };
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

    glBlendFunc(GL_SRC_ALPHA, GL_ONE);	// Set the blending function for translucency
    glEnable(GL_BLEND);			// Enable blending
    glBindTexture(GL_TEXTURE_2D, texture[apple_tex].TexID);
    glEnable(GL_TEXTURE_2D);

    if (TimerGetTime() - AppleFrameTimer > 250) {
       appleframe++;
       AppleFrameTimer = TimerGetTime();
       if (appleframe > 3) appleframe = 0;
    }

    x = appleframe % 4;

         glPushMatrix();
            glTranslatef(apple.x, apple.y+0.5, apple.z);

            glPushMatrix();
            RotateToFace(camera[0].Position, apple);
            glBegin(GL_QUADS);
		glTexCoord2f(x*0.25f + 0.00f, 0.00f); glVertex3f(-0.5f,-0.5f, 0.0f);
		glTexCoord2f(x*0.25f + 0.25f, 0.00f); glVertex3f( 0.5f,-0.5f, 0.0f);
		glTexCoord2f(x*0.25f + 0.25f, 0.25f); glVertex3f( 0.5f, 0.5f, 0.0f);
		glTexCoord2f(x*0.25f + 0.00f, 0.25f); glVertex3f(-0.5f, 0.5f, 0.0f);
            glEnd();
            glPopMatrix();

            glTranslatef(0, 2.5, 0);

            glPushMatrix();
            RotateToFace(camera[0].Position, apple);
            glBegin(GL_QUADS);
		glTexCoord2f(x*0.25f + 0.00f, 0.75f); glVertex3f(-1.0f,-1.0f, 0.0f);
		glTexCoord2f(x*0.25f + 0.25f, 0.75f); glVertex3f( 1.0f,-1.0f, 0.0f);
		glTexCoord2f(x*0.25f + 0.25f, 1.00f); glVertex3f( 1.0f, 1.0f, 0.0f);
		glTexCoord2f(x*0.25f + 0.00f, 1.00f); glVertex3f(-1.0f, 1.0f, 0.0f);
            glEnd();
            glPopMatrix();

         glPopMatrix();

    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);			// Disable blending
}

GLvoid DrawTrees()
{
    GLfloat mat_ambient_branches[] = { 0.9, 0.7, 0.0, 1.0 };
    GLfloat mat_ambient_trunk[] = { 0.9, 0.3, 0.0, 1.0 };
    glBindTexture(GL_TEXTURE_2D, texture[grass_tex].TexID);
    glEnable(GL_TEXTURE_2D);

    for (int loop = 0; loop<numtrees; loop++) {
      glPushMatrix();

      glTranslatef(tree[loop].x, tree[loop].y+2, tree[loop].z);
      glRotatef(90.0, 1.0, 0.0, 0.0);

      glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_trunk);
      GLUquadricObj * cylinder = gluNewQuadric();
      gluQuadricNormals(cylinder, GLU_SMOOTH);
      gluQuadricTexture(cylinder, GL_TRUE);
      gluQuadricOrientation(cylinder, GLU_OUTSIDE);
      gluCylinder(cylinder,wormradius,wormradius,2,20,20);

      glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_branches);

      if (tree[loop].y > -4) {
        glTranslatef(0.0f, 0.0f, -2.0f);

        GLUquadricObj * cylinder2 = gluNewQuadric();
        gluQuadricNormals(cylinder2, GLU_SMOOTH);
        gluQuadricTexture(cylinder2, GL_TRUE);
        gluQuadricOrientation(cylinder2, GLU_OUTSIDE);
        gluCylinder(cylinder2,0,3*wormradius,3,20,20);
      }
      else {
        GLUquadricObj * sphere = gluNewQuadric();
        gluQuadricNormals(sphere, GLU_SMOOTH);
        gluQuadricTexture(sphere, GL_TRUE);
        gluQuadricOrientation(sphere, GLU_OUTSIDE);
        gluSphere(sphere,wormradius*4,20,20);
      }

      glPopMatrix();
    }
    glDisable(GL_TEXTURE_2D);
}

GLvoid DrawWormHole()
{
    GLfloat mat_ambient[] = { 0.4, 0.4, 0.1, 1.0 };
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

    glBlendFunc(GL_SRC_ALPHA, GL_ONE);	// Set the blending function for translucency
    glEnable(GL_BLEND);			// Enable blending
    glBindTexture(GL_TEXTURE_2D, texture[wormhole_tex].TexID);
    glEnable(GL_TEXTURE_2D);
       for (int loop = 0; loop < 2; loop ++) {
         glPushMatrix();
            glTranslatef(hole[loop].x, hole[loop].y, hole[loop].z);

            RotateToFace(camera[0].Position, hole[loop]);

            holespin += 5.0f;

            glRotatef(holespin,0.0f,0.0f,1.0f);     //Spin the disc
            glRotatef(holespin, 0.0f, 0.0f, 0.0f);  //Make it shrink and grow

            glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
            glEnd();
         glPopMatrix();
       }
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);			// Disable blending
}

GLvoid DrawPandora()
{
    int x;
    int y;

    GLfloat mat_ambient[] = { 1.0, 0.7, 0.4, 1.0 };
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

    glBlendFunc(GL_SRC_ALPHA, GL_ONE);	// Set the blending function for translucency
    glEnable(GL_BLEND);			// Enable blending
    glBindTexture(GL_TEXTURE_2D, texture[pandora_tex].TexID);
    glEnable(GL_TEXTURE_2D);
         glPushMatrix();
            glTranslatef(pandora.x, pandora.y, pandora.z);

            RotateToFace(camera[0].Position, pandora);

            pandoraspin -= 5.0f;

            glRotatef(pandoraspin,0.0f,0.0f,1.0f);     //Spin pandora
            glRotatef(pandoraspin, 0.0f, 0.0f, 0.0f);  //Make it shrink and grow

            if (TimerGetTime() - PandoraFrameTimer > 750) {
               pandoraframe++;
               PandoraFrameTimer = TimerGetTime();
               if (pandoraframe > 15) pandoraframe = 0;
            }

            x = pandoraframe % 4;
            y = pandoraframe / 4;

            glBegin(GL_QUADS);
		glTexCoord2f(x*0.25f + 0.00f, y*0.25f + 0.00f); glVertex3f(-0.75f,-0.75f, 0.0f);
		glTexCoord2f(x*0.25f + 0.25f, y*0.25f + 0.00f); glVertex3f( 0.75f,-0.75f, 0.0f);
		glTexCoord2f(x*0.25f + 0.25f, y*0.25f + 0.25f); glVertex3f( 0.75f, 0.75f, 0.0f);
		glTexCoord2f(x*0.25f + 0.00f, y*0.25f + 0.25f); glVertex3f(-0.75f, 0.75f, 0.0f);
            glEnd();
         glPopMatrix();
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);			// Disable blending
}

GLvoid DrawWorm()
{
    GLfloat mat_ambient[] = { 0.0, 0.2, 0.2, 0.7 };
    GLfloat mat_diffuse[] = { 0.0, 0.2, 0.2, 0.7 };
    GLuint wormsegment;
    VECTOR wormseg;
    VECTOR nextwormseg;

    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

    glDisable(GL_TEXTURE_2D);

    glNewList(wormsegment, GL_COMPILE);
       GLUquadricObj * sphere = gluNewQuadric();
       gluQuadricOrientation(sphere, GLU_OUTSIDE);
       gluSphere(sphere,wormradius,20,20);
    glEndList();

    /* Starting at the tail, update each segment location */

    glPushMatrix();
    wormseg.x = light[0].Position.x;
    wormseg.y = light[0].Position.y;
    wormseg.z = light[0].Position.z;

    glTranslatef(wormseg.x, wormseg.y, wormseg.z);

    if (pause == FALSE) {
       if (phaseinsegments > 0) {
          phaseinsegments--;
          numwormsegments++;
       }
       else if (phaseinsegments < 0) {
          worm.pop_back();
          phaseinsegments++;
          numwormsegments--;
       }
       else {
          worm.pop_back();
       }
          worm.push_front(wormseg);
    }

    begin = worm.begin();
    end = worm.end();
    end--; //Otherwise the loop below is called for begin==end too.

    while (begin != end) {
       wormseg = *begin;
       begin++;
       nextwormseg = *begin;
       glTranslatef(nextwormseg.x - wormseg.x,
                    nextwormseg.y - wormseg.y,
                    nextwormseg.z - wormseg.z);
       glCallList(wormsegment);
    }

    glPopMatrix();
    glEnable(GL_TEXTURE_2D);
}

GLvoid DrawLives()
{
    int x;
    int y;

    GLfloat mat_ambient[] = { 0.2, 1.0, 0.1, 1.0 };
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

  glBlendFunc(GL_SRC_ALPHA, GL_ONE);	// Set the blending function for translucency
  glEnable(GL_BLEND);			// Enable blending
  glBindTexture(GL_TEXTURE_2D, texture[life_tex].TexID);
  glEnable(GL_TEXTURE_2D);

  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();
  gluOrtho2D(0, 640, 0, 480);
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();
  glLoadIdentity();

  glDisable(GL_DEPTH_TEST);
  glDisable(GL_LIGHTING);

      glTranslatef(30,460,0);
      for (int loop=0; loop<(lives-1); loop++) {

            if (TimerGetTime() - LifeFrameTimer > 200) {
               lifeframe++;
               LifeFrameTimer = TimerGetTime();
               if (lifeframe > 14) lifeframe = 0;
            }

            x = lifeframe % 4;
            y = lifeframe / 4;

            glBegin(GL_QUADS);
		glTexCoord2f(x*0.25f + 0.00f, y*0.25f + 0.00f); glVertex3f(-10.0f,-10.0f, 0.0f);
		glTexCoord2f(x*0.25f + 0.25f, y*0.25f + 0.00f); glVertex3f( 10.0f,-10.0f, 0.0f);
		glTexCoord2f(x*0.25f + 0.25f, y*0.25f + 0.25f); glVertex3f( 10.0f, 10.0f, 0.0f);
		glTexCoord2f(x*0.25f + 0.00f, y*0.25f + 0.25f); glVertex3f(-10.0f, 10.0f, 0.0f);
            glEnd();

            glTranslatef(25,0,0);
      }

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_LIGHTING);

  glPopMatrix();
  glMatrixMode(GL_PROJECTION);
  glPopMatrix();
  glMatrixMode(GL_MODELVIEW);
  glPopMatrix();

  glDisable(GL_TEXTURE_2D);  
  glDisable(GL_BLEND);
}

GLvoid DrawCross()
{
    int x;
    int y;

    GLfloat mat_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

  glBlendFunc(GL_SRC_ALPHA, GL_ONE);	// Set the blending function for translucency
  glEnable(GL_BLEND);			// Enable blending
  glBindTexture(GL_TEXTURE_2D, texture[cross_tex].TexID);
  glEnable(GL_TEXTURE_2D);

  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();
  gluOrtho2D(0, 640, 0, 480);
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();
  glLoadIdentity();

  glDisable(GL_DEPTH_TEST);
  glDisable(GL_LIGHTING);

      glTranslatef(500,20,0);

      if (TimerGetTime() - CrossFrameTimer > 150) {
         crossframe++;
         CrossFrameTimer = TimerGetTime();
         if (crossframe > 14) crossframe = 0;
      }

      x = crossframe % 4;
      y = crossframe / 4;

      glBegin(GL_QUADS);
         glTexCoord2f(x*0.25f + 0.00f, y*0.25f + 0.00f); glVertex3f(-10.0f,-13.6f, 0.0f);
         glTexCoord2f(x*0.25f + 0.25f, y*0.25f + 0.00f); glVertex3f( 10.0f,-13.6f, 0.0f);
         glTexCoord2f(x*0.25f + 0.25f, y*0.25f + 0.25f); glVertex3f( 10.0f, 13.6f, 0.0f);
         glTexCoord2f(x*0.25f + 0.00f, y*0.25f + 0.25f); glVertex3f(-10.0f, 13.6f, 0.0f);
      glEnd();

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_LIGHTING);

  glPopMatrix();
  glMatrixMode(GL_PROJECTION);
  glPopMatrix();
  glMatrixMode(GL_MODELVIEW);
  glPopMatrix();

  glDisable(GL_TEXTURE_2D);
  glDisable(GL_BLEND);
}

GLvoid DrawSplash()
{
  GLfloat mat_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
  glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

  glBindTexture(GL_TEXTURE_2D, texture[glowworm_tex].TexID);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE);	// Set the blending function for translucency
  glEnable(GL_BLEND);			// Enable blending
  glEnable(GL_TEXTURE_2D);

  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();
  gluOrtho2D(0, 640, 0, 480);
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();
  glLoadIdentity();

      glTranslatef(220,280,0);
            glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-100.0f,-126.0f, 0.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 100.0f,-126.0f, 0.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 100.0f, 126.0f, 0.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-100.0f, 126.0f, 0.0f);
            glEnd();

  glPopMatrix();
  glMatrixMode(GL_PROJECTION);
  glPopMatrix();
  glMatrixMode(GL_MODELVIEW);
  glPopMatrix();

  glDisable(GL_TEXTURE_2D);
  glDisable(GL_BLEND);
}

GLvoid DrawViews()
{
    int x;
    int y;

    GLfloat mat_ambient[] = { 0.2, 1.0, 0.1, 1.0 };
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

  glBlendFunc(GL_SRC_ALPHA, GL_ONE);	// Set the blending function for translucency
  glEnable(GL_BLEND);			// Enable blending
  glBindTexture(GL_TEXTURE_2D, texture[otherview_tex].TexID);
  glEnable(GL_TEXTURE_2D);

  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();
  gluOrtho2D(0, 640, 0, 480);
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();
  glLoadIdentity();

  glDisable(GL_DEPTH_TEST);
  glDisable(GL_LIGHTING);

      glTranslatef(30,430,0);
      for (int loop=0; loop < views; loop++) {

            if (TimerGetTime() - ViewFrameTimer > 200) {
               viewframe++;
               ViewFrameTimer = TimerGetTime();
               if (viewframe > 15) viewframe = 0;
            }

            x = viewframe % 4;
            y = viewframe / 4;

            glBegin(GL_QUADS);
		glTexCoord2f(x*0.25f + 0.00f, y*0.25f + 0.00f); glVertex3f(-10.0f,-10.0f, 0.0f);
		glTexCoord2f(x*0.25f + 0.25f, y*0.25f + 0.00f); glVertex3f( 10.0f,-10.0f, 0.0f);
		glTexCoord2f(x*0.25f + 0.25f, y*0.25f + 0.25f); glVertex3f( 10.0f, 10.0f, 0.0f);
		glTexCoord2f(x*0.25f + 0.00f, y*0.25f + 0.25f); glVertex3f(-10.0f, 10.0f, 0.0f);
            glEnd();

            glTranslatef(25,0,0);
      }

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_LIGHTING);

  glPopMatrix();
  glMatrixMode(GL_PROJECTION);
  glPopMatrix();
  glMatrixMode(GL_MODELVIEW);
  glPopMatrix();

  glDisable(GL_TEXTURE_2D);  
  glDisable(GL_BLEND);
}

GLvoid DrawAir()
{
  float airleft;

  GLfloat mat_ambient[] = { 0.0, 1.0, 1.0, 1.0 };
  glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

  glBlendFunc(GL_SRC_ALPHA, GL_ONE);	// Set the blending function for translucency
  glEnable(GL_BLEND);			// Enable blending
  glBindTexture(GL_TEXTURE_2D, texture[water_tex].TexID);
  glEnable(GL_TEXTURE_2D);

  if (pause == FALSE) {
     airleft = (3500 - (TimerGetTime()- AirTimer))/500.0;
  }
  else {
     airleft = (3500 - (PauseStarted - AirTimer))/500.0;
  }

    glPushMatrix();
    glTranslatef(light[0].Position.x, light[0].Position.y+1.5, light[0].Position.z);

      RotateToFace(camera[0].Position, light[0].Position);

      glBegin(GL_QUADS);
         glTexCoord2f(0.0f, 0.0f); glVertex3f(-1*airleft,-0.1f, 0.0f);
         glTexCoord2f(1.0f, 0.0f); glVertex3f(   airleft,-0.1f, 0.0f);
         glTexCoord2f(1.0f, 1.0f); glVertex3f(   airleft, 0.1f, 0.0f);
         glTexCoord2f(0.0f, 1.0f); glVertex3f(-1*airleft, 0.1f, 0.0f);
      glEnd();
    glPopMatrix();

  glDisable(GL_TEXTURE_2D);    
  glDisable(GL_BLEND);
}

GLvoid DrawFlood()
{
    GLfloat mat_ambient[] = { 0.0, 0.4, 1.0, 1.0 };
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

    glBlendFunc(GL_SRC_ALPHA, GL_ONE);	// Set the blending function for translucency
    glEnable(GL_BLEND);			// Enable blending
    glBindTexture(GL_TEXTURE_2D, texture[water_tex].TexID);
    glEnable(GL_TEXTURE_2D);

    glPushMatrix();

    GLfloat size = (MAP_SIZE*scaleValue)/2;

            glBegin(GL_QUADS);
		glTexCoord2f( 0.0f, 0.0f); glVertex3f(-1*size, waterlevel,    size);
		glTexCoord2f( 1.0f, 0.0f); glVertex3f(   size, waterlevel,    size);
		glTexCoord2f( 1.0f, 1.0f); glVertex3f(   size, waterlevel, -1*size);
		glTexCoord2f( 0.0f, 1.0f); glVertex3f(-1*size, waterlevel, -1*size);
            glEnd();

    glPopMatrix();

    glDisable(GL_TEXTURE_2D);    
    glDisable(GL_BLEND);
}

GLvoid UpdateWormVector()
{
    wormdirection.x = wormspeed * (cos(wormangle.y) + sin(wormangle.y));
    wormdirection.y = wormspeed * (wormdirection.y);
    wormdirection.z = wormspeed * (-1*sin(wormangle.y) + cos(wormangle.y));
}

#include "heightmap.h"

GLvoid UpdateWormPosition()
{
    light[0].Position.x = light[0].Position.x + /*(redrawtime/1000.0)*/light[0].Multiplier*wormdirection.x;
    light[0].Position.z = light[0].Position.z + /*(redrawtime/1000.0)*/light[0].Multiplier*wormdirection.z;
    light[0].Position.y = Height(g_HeightMap, (light[0].Position.x+xzoffset) / scaleValue,
                                             (light[0].Position.z+xzoffset) /scaleValue)*(scaler)
                          + yoffset;
    light[0].Apply();
}

GLvoid KillWorm(float time)
{
       lives--;
       wormspeed = initialwormspeed;
       wormholeactive = FALSE;
       pandoraactive = FALSE;
       drowning = FALSE;
       otherviewactive = FALSE;
       waterlevel = minwaterlevel;
       WormHoleStarted = time;
       TeleportStarted = time;
       PandoraStarted = time;
       WormUpdateStarted = time;
       PandoraFrameTimer = time;
       LifeFrameTimer = time;
       AppleFrameTimer = time;
       AirTimer = time;
       RainSeasonStarted = time;
       SetGLCamera();
       ResetWorm();
}

GLvoid UpdateTimers(float time)
{
       WormHoleStarted += time - PauseStarted;
       TeleportStarted += time - PauseStarted;
       PandoraStarted += time - PauseStarted;
       WormUpdateStarted += time - PauseStarted;
       AirTimer += time - PauseStarted;
       RainSeasonStarted += time - PauseStarted;
}

GLvoid RotateToFace(VECTOR LookAt, VECTOR Object)
{
    float deltax;
    float deltay;
    float deltaz;

    GLfloat theta1;
    GLfloat theta2;

    GLfloat opposite;
    GLfloat adjacent;

            deltax = LookAt.x - Object.x;
            deltay = LookAt.y - Object.y;
            deltaz = LookAt.z - Object.z;

            opposite = deltay;
            adjacent = sqrt((deltax*deltax)+(deltaz*deltaz));

            if (adjacent == 0)
               theta1 = 90.0;
            else
               theta1 = -1*atan(opposite/adjacent)*360/(2*pi);

            opposite = deltax;
            adjacent = deltaz;

            if (adjacent == 0)
               theta2 = 90.0;
            else
               theta2 = atan(opposite/adjacent)*360/(2*pi);

            glRotatef(theta2, 0.0f, 1.0f, 0.0f);    //Rotate to face front
            glRotatef(theta1, 1.0f, 0.0f, 0.0f);    //Rotate to face front
}

GLvoid DrawHighScoreTable()
{
    glPrint(430, 320, 0, "High Scores");

    for (int loop=0; loop<10; loop++) {
      glPrint(400, 300-(10*loop), 1, "%2d %10s %3d",
               loop+1,
               highscoretabledata[loop].name,
               highscoretabledata[loop].score);
    }
}

GLvoid LoadHighScoreTable()
{
	FILE *pFile;

	if (( pFile = fopen( "Data/HighScores.dat", "rb")) == NULL ) {
		MessageBox(NULL, "Couldn't read high scores!", "Error", MB_OK);
		return;
	}

	fread(&highscoretabledata, sizeof(highscore), 10, pFile );

	fclose(pFile);
}

GLvoid SaveHighScoreTable()
{
	FILE *pFile;

	if (( pFile = fopen( "Data/HighScores.dat", "wb")) == NULL ) {
		MessageBox(NULL, "Couldn't update high scores!", "Error", MB_OK);
		return;
	}

	fwrite(&highscoretabledata, sizeof(highscore), 10, pFile );

	fclose(pFile);
}

GLvoid SortHighScoreTable()
{
highscore temphighscore;

   for (int loop=0; loop<10; loop++) {
      for (int loop2=loop; loop2<10; loop2++) {
         if (highscoretabledata[loop].score < highscoretabledata[loop2].score) {
            temphighscore.score = highscoretabledata[loop].score;
            strcpy(temphighscore.name, highscoretabledata[loop].name);
            highscoretabledata[loop].score = highscoretabledata[loop2].score;
            strcpy(highscoretabledata[loop].name, highscoretabledata[loop2].name);
            highscoretabledata[loop2].score = temphighscore.score;
            strcpy(highscoretabledata[loop2].name, temphighscore.name);
         }
      }
   }
}

GLvoid EnterNameInTable()
{
   if (score > highscoretabledata[9].score) {
      highscoretabledata[9].score = score;
      strcpy(highscoretabledata[9].name, name);
      SortHighScoreTable();
   }
}
